package settings

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

// Conf 是一个全局变量，用于存储应用程序的配置信息
var Conf = new(AppConfig)

// AppConfig 定义了应用程序配置的结构体，包含了应用程序的基本配置信息
type AppConfig struct {
	Name         string                 `mapstructure:"name"`       // 应用程序名称
	Mode         string                 `mapstructure:"mode"`       // 应用程序运行模式
	Port         int                    `mapstructure:"port"`       // 应用程序运行端口
	StartTime    string                 `mapstructure:"start_time"` // 程序开始时间
	MachineID    int64                  `mapstructure:"machine_id"` //机器ID
	*LogConfig   `mapstructure:"log"`   // 日志配置信息
	*MySQLConfig `mapstructure:"mysql"` // MySQL数据库配置信息
	*RedisConfig `mapstructure:"redis"` // Redis数据库配置信息
}

// LogConfig 定义了日志配置的结构体，包含了日志的相关配置信息
type LogConfig struct {
	Level      string `mapstructure:"level"`       // 日志级别
	FileName   string `mapstructure:"filename"`    // 日志文件名
	MaxSize    int    `mapstructure:"max_size"`    // 日志文件最大尺寸（MB）
	MaxAge     int    `mapstructure:"max_age"`     // 保留最旧的日志文件天数
	MaxBackups int    `mapstructure:"max_backups"` // 最多保留的日志文件个数
}

// MySQLConfig 定义了MySQL数据库配置的结构体，包含了连接MySQL数据库所需的信息
type MySQLConfig struct {
	Host         string `mapstructure:"host"`           // 数据库主机地址
	Port         int    `mapstructure:"port"`           // 数据库端口
	User         string `mapstructure:"user"`           // 数据库用户名
	Password     string `mapstructure:"password"`       // 数据库密码
	DbName       string `mapstructure:"dbname"`         // 数据库名
	MaxOpenConns int    `mapstructure:"max_open_conns"` // 最大打开的连接数
	MaxIdleConns int    `mapstructure:"max_idle_conns"` // 最大空闲连接数
}

// RedisConfig 定义了Redis数据库配置的结构体，包含了连接Redis数据库所需的信息
type RedisConfig struct {
	Host     string `mapstructure:"host"`      // Redis主机地址
	Port     int    `mapstructure:"port"`      // Redis端口
	Password string `mapstructure:"password"`  // Redis密码
	DB       int    `mapstructure:"db"`        // 使用的数据库编号
	PoolSize int    `mapstructure:"pool_size"` // 连接池大小
}

// Init 用于初始化应用程序的配置信息
// 它会读取配置文件，并将配置信息反序列化到 Conf 全局变量中
// 同时，它还会监视配置文件的变化，当配置文件修改时，自动更新 Conf 中的配置信息
func Init() (err error) {
	viper.SetConfigFile("config.yaml")
	viper.AddConfigPath(".")      // 查找配置文件所在的路径(这里使用相对路径)
	viper.AddConfigPath("./conf") // 可以设置多个查抄配置文件路径
	err = viper.ReadInConfig()
	if err != nil {
		fmt.Printf("viper.ReadInconfig failed,err:%v\n", err)
		return
	}

	// 把读取到的配置信息反序列化到 Conf 全局变量中
	if err := viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper.Unmarshal failed,err:%v\n", err)
	}

	viper.WatchConfig()
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("配置文件修改了")
		if err := viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed,err:%v\n", err)
		}
	})
	return
}
